﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Threading;

namespace MvcEngine.Mvc.Filters
{
    public abstract class RedirectOnErrorAttribute : HandleErrorAttribute
    {
        #region Public properties
        public Type Type { get; set; } 
        #endregion

        #region Public methods
        public override void OnException(ExceptionContext exceptionContext)
        {
            if (!Validate(exceptionContext))
                return;

            if (Type != null && !typeof(Exception).IsAssignableFrom(Type))
                throw new ArgumentException("RedirectOnErrorAttribute's Type property's value must derive from System.Exception.");

            Exception ex = exceptionContext.Exception.InnerException ?? exceptionContext.Exception;

            if (ex.GetType() == typeof(ThreadAbortException))
                return;
            else if (Type == typeof(ThreadAbortException))
                throw new ArgumentException("Cannot catch exceptions of type 'ThreadAbortException'.");

            if (IsExactMatch(ex) || Type == null)
            {
                Redirect(exceptionContext);
            }
        }

        public bool IsExactMatch(Exception exception)
        {
            if (Type != null && exception.GetType() == Type)
                return true;
            else
                return false;
        } 
        #endregion

        #region Protected abstract methods
        protected abstract bool Validate(ExceptionContext exceptionContext);
        protected abstract void Redirect(ExceptionContext exceptionContext); 
        #endregion
    }
}
